#pragma once

#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>
#include "Util.hpp"

//#define MYSELF 1

namespace protocal_ns
{
#define SEP " "
#define SEP_LEN strlen(SEP)
#define HEADER_SEP "\r\n"
#define HEADER_SEP_LEN strlen(HEADER_SEP)

    //"7\r\n10 + 11\r\n" 添加完报头，变成这个样子
    std::string AddHeader(const std::string str)
    {
        std::cout << "AddHeader 之前 : " << str << std::endl;
        std::string res = std::to_string(str.size());
        res += HEADER_SEP;
        res += str;
        res += HEADER_SEP;
        std::cout << "AddHeader 之后 : " << res << std::endl;

        return res;
    }

    //"7\r\n10 + 11\r\n"
    std::string RemoveHeader(const std::string str, int len)
    {
        std::cout << "RemoveHeader 之前 : " << str << std::endl;
        std::string res = str.substr(str.size() - len - HEADER_SEP_LEN, len); // str.size() - len - HEADER_SEP_LEN来到1字符，从1开始切割len长度
        std::cout << "RemoveHeader 之后 : " << res << std::endl;
        return res;
    }

    // const &: 输入
    // *: 输出
    // &: 输入输出
    int ReadPackage(int sock, std::string &inbuffer, std::string *package)
    {
        std::cout << "ReadPackage inbuffer 之前 : " << inbuffer << std::endl;
        char buffer[1024];
        ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if (n <= 0)
            return -1;
        else
            buffer[n] = '\0';
        inbuffer += buffer;
        std::cout << "ReadPackage inbuffer 之中 : " << inbuffer << std::endl;

        size_t pos = inbuffer.find(HEADER_SEP);
        if (pos == std::string::npos) // 未读取完
            return -1;
        std::string lenstr = inbuffer.substr(0, pos); // 切割出前面的数字
        int len = Util::ToInt(lenstr);
        int packageLen = lenstr.size() + len + 2 * HEADER_SEP_LEN; // 该package的长度
        if (inbuffer.size() < packageLen)                          // inbuffer没有满足该package的长度，未读取完毕
            return -1;
        *package = inbuffer.substr(0, packageLen); // 赋值
        inbuffer.erase(0, packageLen);             // 删除该报文

        std::cout << "ReadPackage inbuffer 之后 : " << inbuffer << std::endl;
        return len;
    }

    class Request
    {
    public:
        Request()
        {}

        Request(int x, int y, char op)
            : _x(x), _y(y), _op(op)
        {
        }

        bool Serialize(std::string *outstr)
        {
#ifdef MYSELF
            std::string x = std::to_string(_x);
            std::string y = std::to_string(_y);
            *outstr = x + SEP + _op + SEP + y;
#else
            Json::Value root;// Value: 一种万能对象, 接受任意的kv类型
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            //Json::FastWriter writer;//用来序列化
            Json::StyledWriter writer;//风格更雅
            *outstr = writer.write(root);
#endif
            return true;
        }

        bool DeSerialize(const std::string &outstr)
        {
#ifdef MYSELF
            std::vector<std::string> result;
            Util::StringSplit(outstr, SEP, &result);
            if (result.size() != 3)
                return false;
            if (result[1].size() != 1)
                return false;
            _x = Util::ToInt(result[0].c_str());
            _y = Util::ToInt(result[2].c_str());
            _op = result[1][0];
#else
            Json::Value root;
            Json::Reader reader;//用来反序列化
            reader.parse(outstr,root);
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();
#endif
           return true;
        }

        ~Request()
        {
        }

    public:
        int _x;
        int _y;
        char _op;
    };

    class Reponse
    {
    public:
        Reponse()
        {}

        Reponse(int result, int exit_code)
            : _result(result), _exit_code(exit_code)
        {
        }

        bool Serialize(std::string *outstr)
        {
#ifdef MySELF
            std::string result = std::to_string(_result);
            std::string exit_code = std::to_string(_exit_code);
            *outstr = result + SEP + exit_code;
#else
            Json::Value root;
            root["result"] = _result;
            root["exit_code"] = _exit_code;
            //Json::FastWriter writer;
            Json::StyledWriter writer;//风格更雅
            *outstr = writer.write(root);
#endif
            return true;
        }

        bool DeSerialize(const std::string str)
        {
#ifdef MYSELF
            std::vector<std::string> result;
            Util::StringSplit(str, SEP, &result);
            if (result.size() != 2)
                return false;
            _result = Util::ToInt(result[0]);
            _exit_code = Util::ToInt(result[1]);
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(str,root);
            _result = root["result"].asInt();
            _exit_code = root["exit_code"].asInt();
#endif
            return true;
        }

        ~Reponse()
        {
        }

    public:
        int _result;
        int _exit_code;
    };
}
